<?php
class Roles extends Dao
{
	private static $_instance = null;
	protected $_db = null, $_cache = null;
	
	protected function __construct()
	{
		parent::__construct();
	}
	
	public static function getInstance() 
    {
        if (null === self::$_instance) {
            self::$_instance = new self();
        }
        return self::$_instance;
    }
	
	
	public function getList(array $args = array(), $intPage = 1, $intLimit = MIN_ROWS_PER_PAGE)
	{
		try{
			$defaults = array(		
			);
			$args = $this->args_merge($defaults, $args);
			
			$intStart = ($intPage-1)*$intLimit;
			
			$cmd = $this->_db->createCommand('SELECT SQL_CALC_FOUND_ROWS role_id, role_name, role_description, role_is_default, role_is_admin FROM tbl_roles');
			
			$arrResults = $cmd->queryAll();
			if(!empty($arrResults)){
				$arrResults[0]['total_rows'] = $this->_db->createCommand('SELECT FOUND_ROWS();')->queryScalar();
			}
			return $arrResults;
		} catch(Exception $ex){
			throw new Exception($ex->getMessage());
		}
	}
	
	public function get($id)
	{
		try{
			$strSql = " SELECT role_id, role_name, role_description, role_is_default, role_is_admin
						FROM tbl_roles
						WHERE role_id=:id";
			$cmd = $this->_db->createCommand($strSql);
			$cmd->bindParam(":id",$id,PDO::PARAM_STR);
			return $arrResults = $cmd->queryRow();
		} catch(Exception $ex){
			throw new Exception($ex->getMessage());
		}
	}
	
	public function insert(array $args)
	{		
		try{
			$defaults = array(
				'role_name' => null,
				'role_description' => null,
				'role_is_default' => 0,
				'role_is_admin' => 0
			);
			$args = $this->args_merge($defaults, $args);
			
			$cmd = $this->_db->createCommand();
			$cmd->insert('tbl_roles',$args);
			return Yii::app()->db->getLastInsertId();
		} catch(Exception $ex){
			throw new Exception($ex->getMessage());
		}
	}
	
	public function update($id, array $args)
	{		
		try{
			$defaults = array(
				'role_name' => null,
				'role_description' => null,
				'role_is_default' => 0,	
				'role_is_admin' => 0
			);
			$args = $this->args_merge($defaults, $args);
			
			$cmd = $this->_db->createCommand();
			return $cmd->update('tbl_roles',$args, 'role_id=:id', array(':id'=>$id));
		} catch(Exception $ex){
			throw new Exception($ex->getMessage());
		}
	}
	
	public function delete($id){
		try{
			//remove user in role
			$cmd = $this->_db->createCommand();
			$cmd->delete('tbl_user_role', 'role_id=:id', array(':id'=>$id));
			//remove role's permissions
			$cmd->delete('tbl_role_permission', 'role_id=:id', array(':id'=>$id));
			//delete role
			return $cmd->delete('tbl_roles', 'role_id=:id', array(':id'=>$id));			
		} catch(Exception $ex){
			throw new Exception($ex->getMessage());
		}
	}
	
	public function getUserRoles($userId, array $args = array(), $returnStyle = RETURN_ASSOC_ARRAY){
		if(empty($userId)) throw new Exception('User can not null');
		try{
			$defaults = array(
				'role_is_admin' => null,
				'role_is_default' => null,
			);
			$args = $this->args_merge($defaults, $args);
			
			$strSql = " SELECT r.role_id, r.role_name
						FROM tbl_user_role ur INNER JOIN tbl_roles r ON (
							ur.role_id = r.role_id AND 
							ur.user_id = :uid AND
							r.role_is_admin = IFNULL(:role_is_admin, r.role_is_admin) AND
							r.role_is_default = IFNULL(:role_is_default, r.role_is_default) 
						)
					  ";
			$cmd = $this->_db->createCommand($strSql);
			$cmd->bindParam(":uid",$userId,PDO::PARAM_STR);
			$cmd->bindParam(":role_is_admin",$args['role_is_admin'],PDO::PARAM_INT);
			$cmd->bindParam(":role_is_default",$args['role_is_default'],PDO::PARAM_INT);
			$arrResults = $cmd->queryAll();
			if($returnStyle === RETURN_NUMERIC_ARRAY){
				$arrTemp = array();
				foreach($arrResults as $R){
					$arrTemp[$R['role_id']] = $R['role_name'];	
				}
				$arrResults = $arrTemp;
			}
			return $arrResults;
		} catch(Exception $ex){
			throw new Exception($ex->getMessage());
		}
	}
	
	//if roleId is array, means user belongs to many roles
	//if roleId null means remove user from all roles
	public function updateUserRole($userId, $roleId = null){
		if(empty($userId)) throw new Exception('User can not null');
		try{
			$cmd = $this->_db->createCommand();
			//remove user from roles
			$cmd->delete('tbl_user_role', 'user_id=:id', array(':id'=>$userId));
			//add new roles
			if(!is_array($roleId)) $roleId = array($roleId);
			$strSql = 'INSERT INTO tbl_user_role (user_id, role_id) VALUES ';
			$values = array();
			foreach($roleId as $role){
				$values[] = "({$userId}, {$role})";
			}
			$strSql .= implode(',', $values);
			return $this->_db->createCommand($strSql)->execute();			
		} catch(Exception $ex){
			throw new Exception($ex->getMessage());
		}
	}
}